//--------------------------------------------------------------------
//     Author:Howe
//     Date: 2021-04-13 21:46:32 
//     Description:对此文件的更改可能会导致不正确的行为，并且如果重新生成代码，这些更改将会丢失。
//--------------------------------------------------------------------
using System;
using System.Threading.Tasks;
using Kylin.Wiki.Core;
using Kylin.Wiki.Services;
using Kylin.Wiki.Model.Entity;
using Kylin.Wiki.IService;
using Kylin.Wiki.Core.Extensions.AutofacManager;
using Kylin.Wiki.Repository;
using System.Collections.Generic;
using Kylin.Wiki.Model.View;
using System.Linq; 
using Kylin.Wiki.Model.Dto;
using Kylin.Wiki.Model.Api;
using Kylin.Wiki.Core.Enum;
using Kylin.Wiki.Core.Utilities;
using System.IO;
using System.Linq.Expressions;
using Mapster;

namespace Kylin.Wiki.Services
{
    /// <summary>
    /// Project_DocumentServices
    /// </summary>	
    public class DocumentService : Service<Document>, IDocumentService, IDependency
    {
        private readonly IDocument_UserService _document_UserService;

         

        public DocumentService(IDocument_UserService document_UserService, IUnitOfWork unitOfWork,
            IRepository<Document> repository) : base(unitOfWork, repository)
        {
            base.UnitOfWork = unitOfWork;
            base.Repository = repository; 
            _document_UserService = document_UserService; 
        }

        /// <summary>
        /// 创建Wiki
        /// </summary>
        /// <param name="documentDTO"></param>
        /// <param name="webRootPath"></param>
        /// <returns></returns>
        public ApiResult<bool> Create(DocumentDTO documentDTO, string webRootPath)
        {
            var document = documentDTO.Adapt<Document>();
            string path = string.Empty;
            string fileExt = ".md";
            if (documentDTO.Pid != 0)
            {
                var pDocument = base.FindFirst(x => x.ID == document.PID);
                //判断是否父级是否存在
                if (pDocument == null)
                    return new ApiResult<bool>(false, HttpStateCode.Error, "该Wiki不存在");
                List<int> plist = new List<int>();
                GetPath(pDocument, ref plist);
                path = string.Join(',', plist);
                document.Path = path;
            }
            else
            {
                document.Path = "0";
            }
            //if (string.IsNullOrEmpty(documentDTO.Content))
            //    return new ApiResult<bool>(false, HttpStateCode.Error, "请输入内容"); 
            //写入文件
            if (!string.IsNullOrEmpty(documentDTO.Content))
            {
                string filePath = string.Empty;
                if (document.Path.Equals("0"))
                {
                    filePath = $"/{document.DocumentName}";
                }
                else
                {
                    var pid = document.Path.Split(',');
                    var pDocumentNames = string.Join('/', base.Find(x => pid.Contains(x.ID.ToString())).Select(x => x.DocumentName).ToList());
                    filePath = $"/{pDocumentNames}/{document.DocumentName}";
                }
                filePath = Path.Combine(webRootPath, "Files/" + filePath);

                if (!FileHelper.DirectoryExists(filePath))
                    FileHelper.FolderCreate(filePath);
                string fileName = document.DocumentName + fileExt;

                FileHelper.WriteFile(filePath + "/" + fileName, documentDTO.Content);
            }
            //保存数据
            base.Add(document, true);
            //添加wiki与用户关系
            var document_user = new Document_User
            {
                CreateBy = document.CreateBy,
                CreateOn = DateTime.Now,
                DocumentID = document.ID,
                Permission = 2,
                IsDelete = "0",
                UpdateBy = document.UpdateBy,
                UpdateOn = DateTime.Now,
                UserID = documentDTO.UserId
            };
            var flag = _document_UserService.Add(document_user, true);
            return new ApiResult<bool>(flag > 0, HttpStateCode.Success, "添加成功");

        }


        /// <summary>
        /// 更新Wiki
        /// </summary>
        /// <param name="documentDTO"></param>
        /// <param name="webRootPath"></param>
        /// <returns></returns>
        public ApiResult<bool> Update(DocumentDTO documentDTO, string webRootPath)
        {
            if (!base.Exists(x => x.ID == documentDTO.ID))
                return new ApiResult<bool>(false, HttpStateCode.Error, "该Wiki不存在");
            string path = string.Empty;
            string fileExt = ".md";
            //写入文件
            if (!string.IsNullOrEmpty(documentDTO.Content))
            {
                var oldDocument = base.FindFirst(x => x.ID == documentDTO.ID);
                var pid = oldDocument.Path.Split(',');
                var pDocumentNames = string.Join('/', base.Find(x => pid.Contains(x.ID.ToString())).Select(x => x.DocumentName).ToList());
                string filePath = $"/{pDocumentNames}/{documentDTO.DocumentName}";
                filePath = Path.Combine(webRootPath, "Files/" + filePath);

                if (!FileHelper.DirectoryExists(filePath))
                    FileHelper.FolderCreate(filePath);
                string fileName = documentDTO.DocumentName + fileExt;

                FileHelper.WriteFile(filePath + "/" + fileName, documentDTO.Content);

                //删除旧的文件夹下的文件
                if (oldDocument.DocumentName != documentDTO.DocumentName)
                {
                    FileHelper.DeleteFolder(Path.Combine(webRootPath, "Files/" + pDocumentNames + "/" + oldDocument.DocumentName));
                }

            }
            var document = documentDTO.Adapt<Document>();
            Expression<Func<Document, object>>[] updatedProperties =
            {
                   p=>p.DocumentName,
                   p=>p.OrderNum,
                   p=>p.UpdateBy,
                   p=>p.UpdateOn
            };

            return new ApiResult<bool>(base.Update(document, updatedProperties, true) > 0, HttpStateCode.Success, "添加成功");
        }
        /// <summary>
        /// 根据ID获取Wiki
        /// </summary>
        /// <param name="wikiId"></param>
        /// <returns></returns>
        public ApiResult<DocumentViewVM> Get(int wikiId,int userId, string webRootPath)
        {
            ApiResult<DocumentViewVM> result = new ApiResult<DocumentViewVM>();
            var document = base.Repository.FindFirst(x => x.ID == wikiId);
            string filePath = string.Empty;
            if (document.Path.Equals("0"))
            {
                filePath = $"/{document.DocumentName}";
            }
            else
            {
                var pid = document.Path.Split(',');
                var pDocumentNames = string.Join('/', base.Find(x => pid.Contains(x.ID.ToString())).Select(x => x.DocumentName).ToList());
                filePath = $"/{pDocumentNames}/{document.DocumentName}";
            }
            filePath = Path.Combine(webRootPath, "Files/" + filePath);

            if (!FileHelper.DirectoryExists(filePath))
                FileHelper.FolderCreate(filePath);
            string fileName = document.DocumentName + ".md";
            var content = FileHelper.ReadFile(filePath + "/" + fileName);
            DocumentViewVM documentViewVM =document.Adapt<DocumentViewVM>();
            documentViewVM.Content = content;
            var documentUser = _document_UserService.FindFirst(x => x.DocumentID == wikiId && x.UserID == userId);
            documentViewVM.UserID = documentUser.UserID;
            documentViewVM.Permission = documentUser.Permission;
            result.Data = documentViewVM;
            return result;
        }

        /// <summary>
        /// 根据用户获取Wiki集合
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public List<DocumentVM> GetList(int userId)
        {
            List<DocumentVM> list = new List<DocumentVM>();
            var document_user = _document_UserService.Find(x => x.UserID == userId);

            //查询文档
            var document = base.Repository.Find(x => 1 == 1)
                .OrderBy(x => x.CreateOn)
                .OrderBy(x => x.ID);

            var data = document.Join(document_user, d => d.ID, du => du.DocumentID, (d, du) => d);
            var documentVMs = data.Adapt<List<DocumentVM>>();
            return ResolveUserMenuTree(documentVMs);
        }


        /// <summary>
        /// 生成属性结构
        /// </summary>
        /// <param name="menus"></param>
        /// <param name="parentId"></param>
        /// <returns></returns>
        private List<DocumentVM> ResolveUserMenuTree(List<DocumentVM> documentVMs, int parentId = 0)
        {
            List<DocumentVM> documents = new List<DocumentVM>();

            foreach (var document in documentVMs.Where(m => m.PID == parentId).OrderBy(m => m.OrderNum))
            {
                var childrenMenu = ResolveUserMenuTree(documentVMs, document.ID);
                document.Children = childrenMenu;
                documents.Add(document);
            }

            return documents.OrderBy(x => x.ID).ToList();
        }

        /// <summary>
        /// 递归获取Path
        /// </summary>
        /// <param name="pid"></param>
        /// <returns></returns>
        private void GetPath(Document document, ref List<int> pList)
        {
            pList.Add(document.ID);
            if (document.PID != 0)
            {
                GetPath(base.FindFirst(x => x.ID == document.PID), ref pList);
            }
        }

    }

}
